﻿/*----------------------------------------------------------------
// Copyright (C) 2018 
// author：meng cheng xin
// data：2018/3/1
// describe：UI管理类
//----------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;


public enum EWindowLayerEnum
{
    EffectLayer,
    HUDLayer,
    PopupLayer,
    NoticeLayer,
    LoadingLayer,

}
public enum EWindowFadeEnum
{
    None,
    Auto,
    ScaleIn,

}
public class WindowManager : Singleton<WindowManager>, IWindowManager
{

    //private readonly string uiRootName = "UGUIRoot";
    private readonly string uiRootName = "study_ugui_root/UGUIRoot";

    private Canvas _canvas;
    public Canvas canvas
    {
        get { return _canvas; }
    }

    private Camera _camera;
    public Camera camera
    {
        get { return _camera; }
    }

    private EventSystem _eventSystem;
    public EventSystem eventSystem
    {
        get
        {
            return EventSystem.current;
            //return _eventSystem;
        }
    }
    private UGUICurveHolder _curveHolder;
    public UGUICurveHolder curveHolder
    {
        get { return _curveHolder; }
    }


    private GameObject m_uiRoot;

    private Transform EffectWindow;
    private Transform HUDWindow;
    private Transform PopupWindow;
    private Transform NoticeWindow;
    private Transform LoadingWindow;


    private Dictionary<string, BaseWindow> m_WindowDict = new Dictionary<string, BaseWindow>();
    private Dictionary<string, UGUIBaseHolder> m_HolderDict = new Dictionary<string, UGUIBaseHolder>();

    public override void Init()
    {
        base.Init();
        LoadUIRoot();
        WindowRegister.InitAllWindows();
    }

    public override void UnInit()
    {
        base.UnInit();

        m_WindowDict.Clear();
        foreach (UGUIBaseHolder holder in m_HolderDict.Values)
        {
            if (holder != null)
            {
                GameObject.Destroy(holder.gameObject);
            }
        }
        m_HolderDict.Clear();
        if (m_uiRoot != null)
            GameObject.Destroy(m_uiRoot);
    }

    public void OpenWindow(string name, params object[] paramArray)
    {
        OpenWindow(name, EWindowLayerEnum.HUDLayer, paramArray);
    }

    public void OpenWindow(string name, EWindowFadeEnum fadeType, params object[] paramArray)
    {
        OpenWindow(name, fadeType, EWindowLayerEnum.HUDLayer, paramArray);
    }

    public void OpenWindow(string name, EWindowLayerEnum layer, params object[] paramArray)
    {
        OpenWindow(name, EWindowFadeEnum.None, layer, paramArray);
    }

    public void OpenWindow(string name, EWindowFadeEnum fadeType, EWindowLayerEnum layer, params object[] paramArray)
    {
        //Debug.LogError("OpenWindow:" + name);
        if (m_HolderDict.ContainsKey(name))
        {
            UGUIBaseHolder holder = m_HolderDict[name];
            if (holder != null)
            {
                holder.transform.SetAsLastSibling();
                holder.OpenWindow(fadeType, layer, paramArray);
                holder.RefreshWindow();
                return;
            }
            m_HolderDict.Remove(name);
        }

        GameObject go = Res.LoadObj(name);

        if (go == null)
        {
            Debug.LogError("load ui error! name:" + name);
            return;
        }

        switch (layer)
        {
            case EWindowLayerEnum.EffectLayer:
                go.transform.SetParent(EffectWindow);
                break;
            case EWindowLayerEnum.HUDLayer:
                go.transform.SetParent(HUDWindow);
                break;
            case EWindowLayerEnum.PopupLayer:
                go.transform.SetParent(PopupWindow);
                break;
            case EWindowLayerEnum.NoticeLayer:
                go.transform.SetParent(NoticeWindow);
                break;
            case EWindowLayerEnum.LoadingLayer:
                go.transform.SetParent(LoadingWindow);
                break;
        }
        go.SetActive(true);
        go.transform.localPosition = Vector3.zero;
        go.transform.localScale = Vector3.one;
        go.transform.localRotation = Quaternion.identity;
        RectTransform rt = go.transform as RectTransform;
        rt.anchoredPosition3D = Vector3.zero;
        rt.sizeDelta = Vector2.zero;

        go.transform.SetAsLastSibling();

        UGUIBaseHolder uh = null;
        BaseWindow window = GetRegisterWindow(name);
        if (window != null)
        {
            uh = go.AddComponent<UGUIHolder>();
            uh.Register(name, window);
        }
        else
        {
            // to lua
            uh = go.AddComponent<UGUILuaHolder>();
            uh.Register(name);
        }
        uh.OpenWindow(fadeType, layer, paramArray);
        //uh.RefreshWindow();

        m_HolderDict.Add(name, uh);
    }

    public void ReplaceWindow(string name, EWindowLayerEnum layer)
    {
        UGUIBaseHolder holder = GetPopWindowHolder(layer);
        if (holder != null)
        {
            holder.CloseWindow();
            holder.transform.SetAsFirstSibling();
        }
        OpenWindow(name, layer);
    }

    /// <summary>
    /// 关闭窗口
    /// </summary>
    /// <param name="name">窗口名字</param>
    /// <param name="isCache">是否需要缓存该窗口，为True不会Destroy</param>
    /// <param name="callback">窗口关闭回调事件（某些有关闭的动画过程）</param>
    public void CloseWindow(string name, bool isCache = false, System.Action callback = null)
    {
        //Debug.LogError("CloseWindow:" + name);
        if (m_HolderDict.ContainsKey(name))
        {
            UGUIBaseHolder holder = m_HolderDict[name];
            if (!holder.isOpen)
                return;
            holder.CloseWindow(()=>
            {
                holder.transform.SetAsFirstSibling();

                if (!isCache)
                {
                    m_HolderDict.Remove(name);
                    GameObject.Destroy(holder.gameObject);
                }
                if (callback != null)
                    callback();
            });

            RefreshWindowHolder(holder.WindowLayer);
        }
    }

    /// <summary>
    /// 获取某个窗口是否打开
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public bool IsOpenWindow(string name)
    {
        UGUIBaseHolder holder = GetUGUIHolder(name);
        if (holder != null)
            return holder.isOpen;
        return false;
    }

    public void RegisterWindow(string name, BaseWindow window)
    {
        //window.Register(name);
        m_WindowDict.Add(name, window);
    }

    public void OnUpdate(float deltaTime)
    {
         
    }

    private void RefreshWindowHolder(EWindowLayerEnum layer)
    {
        foreach (UGUIBaseHolder holder in m_HolderDict.Values)
        {
            if (holder.isOpen && holder.WindowLayer == layer)
            {
                holder.RefreshWindow();
            }
        }
    }

    private UGUIBaseHolder GetPopWindowHolder(EWindowLayerEnum layer)
    {
        switch (layer)
        {
            case EWindowLayerEnum.EffectLayer:
                return EffectWindow.childCount > 0 ? EffectWindow.GetChild(EffectWindow.childCount - 1).GetComponent<UGUIBaseHolder>() : null;
            case EWindowLayerEnum.HUDLayer:
                return HUDWindow.childCount > 0 ? HUDWindow.GetChild(HUDWindow.childCount - 1).GetComponent<UGUIBaseHolder>() : null;
            case EWindowLayerEnum.PopupLayer:
                return PopupWindow.childCount > 0 ? PopupWindow.GetChild(PopupWindow.childCount - 1).GetComponent<UGUIBaseHolder>() : null;
            case EWindowLayerEnum.NoticeLayer:
                return NoticeWindow.childCount > 0 ? NoticeWindow.GetChild(NoticeWindow.childCount - 1).GetComponent<UGUIBaseHolder>() : null;
            case EWindowLayerEnum.LoadingLayer:
                return LoadingWindow.childCount > 0 ? LoadingWindow.GetChild(LoadingWindow.childCount - 1).GetComponent<UGUIBaseHolder>() : null;
            default:
                return null;
        }
    }

    private UGUIBaseHolder GetUGUIHolder(string name)
    {
        if (m_HolderDict.ContainsKey(name))
            return m_HolderDict[name];
        return null;
    }

    private void LoadUIRoot()
    {
        m_uiRoot = Res.LoadObj(uiRootName);
        if (m_uiRoot == null)
        {
            Debug.LogError("Load ui root error! Name:" + uiRootName);
            return;
        }

        GameObject.DontDestroyOnLoad(m_uiRoot);
        m_uiRoot.transform.position = new Vector3(0, 0, 0);
        m_uiRoot.transform.position = new Vector3(0, 1000, 0);
        _canvas = m_uiRoot.GetComponentInChildren<Canvas>();
        _camera = m_uiRoot.GetComponentInChildren<Camera>();
        _eventSystem = m_uiRoot.GetComponentInChildren<EventSystem>();
        EffectWindow = _canvas.transform.Find("EffectWindow");
        HUDWindow = _canvas.transform.Find("HUDWindow");
        PopupWindow = _canvas.transform.Find("PopupWindow");
        NoticeWindow = _canvas.transform.Find("NoticeWindow");
        LoadingWindow = _canvas.transform.Find("LoadingWindow");
        _curveHolder = m_uiRoot.GetComponent<UGUICurveHolder>();
    }

    private BaseWindow GetRegisterWindow(string name)
    {
        if (m_WindowDict.ContainsKey(name))
            return m_WindowDict[name];
        return null;
    }

}
